//********************************************************************
//	created:	16:10:2011   20:53
//	filename: 	timermanager.cpp
//	author:		tiamo
//	purpose:	timer manager
//********************************************************************

#include "stdafx.h"
#include "timermanager.h"

namespace utils
{
	//
	// register timer
	//
	utils::SmartPointer<TimerManager::Timer> TimerManager::registerTimer(uint32_t delaySecond, bool oneShot, TimerRoutine&& timerRoutine)
	{
		SmartPointer<Timer> theTimer										= new Timer(delaySecond, oneShot, std::move(timerRoutine));
		mTimerList.push_back(theTimer);
		return theTimer;
	}

	//
	// update timer
	//
	void TimerManager::updateTimer(utils::SmartPointer<Timer> const& theTimer, uint32_t delaySecond)
	{
		theTimer->mDelaySecond												= delaySecond;
		theTimer->mStartSecond												= static_cast<uint32_t>(time(nullptr));
	}

	//
	// unregister timer
	//
	void TimerManager::unregisterTimer(utils::SmartPointer<Timer> const& theTimer)
	{
	#if 0
		auto it																= std::find(mTimerList.begin(), mTimerList.end(), theTimer);
		if(it == mTimerList.end())
			ThrowException(L"TimerManager(%p): unable to find timer(%p)", this, theTimer.get());
	#endif

		theTimer->mRoutine													= nullptr;
	}

	//
	// run frame
	//
	void TimerManager::runFrame()
	{
		uint32_t nowTime													= static_cast<uint32_t>(time(nullptr));
		uint32_t elapsedSecond												= nowTime - mLastSecond;
		if(!elapsedSecond)
			return;

		for(auto it = mTimerList.begin(); it != mTimerList.end();)
		{
			SmartPointer<Timer> const& theTimer								= *it;
			bool needDelete													= !theTimer->mRoutine;
			if(!needDelete && theTimer->mStartSecond + theTimer->mDelaySecond <= nowTime)
			{
				try
				{
					bool autoRemove											= theTimer->mRoutine(nowTime - theTimer->mStartSecond);
					if(!theTimer->mOneShot)
						theTimer->mStartSecond								= nowTime;
					else if(autoRemove)
						needDelete											= true;
				}
				catch(std::exception& e)
				{
					LogError(L"TimerManager(%p): exception (%ls)", this, utils::Exception::getMessage(e).c_str());
				}
			}

			if(needDelete)
				it															= mTimerList.erase(it);
			else
				++ it;
		}

		mLastSecond															= nowTime;
	}
}
